#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

#include <fibthread.h>

void * foo(void *arg);
void * bar(void *arg);
void * sigint(void *arg);
void sigint_handler(int signo);


int main(int argc, char *argv[]){

	sigset_t th_sigmask;
	int result, error;
	fibthread_t tfoo, tbar, tsig;
	fibthread_attr_t tattr;

	/* Now start waiting for threads to finish */
	if ((error = fibthread_attr_init(&tattr)) != 0)
		fprintf(stderr, "Failed to create attribute object: %s\n",strerror(error));
	else if ((error = fibthread_attr_setdetachstate(&tattr,FIBTHREAD_CREATE_DETACHED)) != 0)
		fprintf(stderr, "Failed to set attribute state to detached: %s\n",
						  strerror(error));

	/* First we block all of the signals so
	 * the created children inherits them */

	sigfillset(&th_sigmask);
	if((result = fibthread_sigmask(SIG_SETMASK, &th_sigmask, NULL)) != 0)
		fprintf(stderr, "fibthread_sigmask : %s \n",strerror(result));

	/* Now create the threads */
	if((result = fibthread_create(&tfoo, &tattr, foo, NULL)) != 0)
			fprintf(stderr, "fibthread_create : %s \n",strerror(result));
	if((result = fibthread_create(&tbar, &tattr, bar, NULL)) != 0)
				fprintf(stderr, "fibthread_create : %s \n",strerror(result));
	if((result = fibthread_create(&tsig, &tattr, sigint, NULL)) != 0)
				fprintf(stderr, "fibthread_create : %s \n",strerror(result));


	printf("Main thread is exiting ... \n");
	fibthread_exit(0);

	return 0;
}


void * foo(void *arg){

	int i = 0;

	for(i = 0; i < 5; i++){
		printf("In foo ... \n");
		sleep(10);
		fibthread_yield();
	}

	return NULL;
}

void * bar(void *arg){
	int i = 0;

	for(i = 0; i < 5; i++){
		printf("In bar ... \n");
		sleep(10);
		fibthread_yield();
	}

	return NULL;
}

void * sigint(void *arg){
	int result, i = 0;
	sigset_t sigint_set;
	struct sigaction siga;

	/* Set the sigaction here */
	siga.sa_handler = sigint_handler;
	siga.sa_flags = 0;
	sigfillset(&siga.sa_mask);

	if(sigaction(SIGINT, &siga, NULL) < 0)
		fprintf(stderr, "sigaction : %s \n",strerror(errno));

	sigemptyset(&sigint_set);
	sigaddset(&sigint_set, SIGINT);

	if((result = fibthread_sigmask(SIG_UNBLOCK, &sigint_set, NULL)) != 0)
			fprintf(stderr, "fibthread_sigmask-sigint : %s \n",strerror(result));

	for(i = 0; i < 5; i++){
		printf("In sigint ... \n");
		sleep(10);
		fibthread_yield();
	}

	return NULL;
}

void sigint_handler(int signo){

	printf("Received SIGINT \n");

}
